package com.ruoyi.dingtalk.service.impl;

import com.dingtalk.api.DefaultDingTalkClient;
import com.dingtalk.api.DingTalkClient;
import com.dingtalk.api.request.OapiGetJsapiTicketRequest;
import com.dingtalk.api.response.OapiGetJsapiTicketResponse;
import com.dingtalk.api.response.OapiGettokenResponse;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.dingtalk.service.DingTalkApiService;
import com.ruoyi.dingtalk.util.DingTalkUtil;
import com.taobao.api.ApiException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;


/**
 * 钉钉Api服务
 *
 * @author xueyu
 */
@Slf4j
@Service(value = "dingTalkApiServiceImpl")
public class DingTalkApiServiceImpl implements DingTalkApiService {


    private RedisCache redisCache;


    /**
     * 获取AccessToken
     *
     * @param ddAppKey    钉钉应用key
     * @param ddAppSecret 钉钉应用密钥
     * @return String
     * @throws ApiException 钉钉接口ApiException
     */
    @Override
    public String getAccessToken(String ddAppKey, String ddAppSecret) throws ApiException {
        if (StringUtils.isEmpty(ddAppKey) || StringUtils.isEmpty(ddAppSecret)) {
            throw new ServiceException("没有配置钉钉应用id或秘钥");
        }
        String accessToken;
        Map<String, Object> tokenMapCache = redisCache.getCacheObject(DING_TOKEN_KEY);
        if (tokenMapCache != null) {
            accessToken = tokenMapCache.get("accessToken") == null ? "" : tokenMapCache.get("accessToken").toString();
            Long oldTime = tokenMapCache.get("curTime") == null ? 0 : Long.parseLong(tokenMapCache.get("curTime").toString());
            Long curTime = System.currentTimeMillis();
            //过期时间之内
            if (StringUtils.isNotEmpty(accessToken) && (curTime - oldTime) < DING_TOKEN_EXPIRE_TIME) {
                return accessToken;
            }
        }
        //没有缓存  就发请求获取
        OapiGettokenResponse response = DingTalkUtil.getAccessTokenByApi(ddAppKey, ddAppSecret);
        if (response.getErrcode() != 0) {
            throw new ServiceException(response.getErrmsg());
        }
        Long curTime = System.currentTimeMillis();
        accessToken = response.getAccessToken();
        Map<String, Object> tokenMap = new HashMap<>();
        tokenMap.put("curTime", curTime);
        tokenMap.put("accessToken", accessToken);
        tokenMap.put("expiresIn", response.getExpiresIn());
        redisCache.setCacheObject(DING_TOKEN_KEY, tokenMap, response.getExpiresIn().intValue(), TimeUnit.SECONDS);
        return accessToken;
    }


    /**
     * 获取钉钉签名jsapiTicket
     *
     * @param ddAppKey    钉钉应用AppKey
     * @param accessToken 用户授权码
     * @return String
     * @throws ApiException ApiException
     */
    @Override
    public String getJsapiTicket(String ddAppKey, String accessToken) throws ApiException {
        String cacheKey = "DING:JSAPI:".concat("APPKEY_" + ddAppKey);
        String jsapiTicket = redisCache.getCacheObject(cacheKey);
        if (StringUtils.isBlank(jsapiTicket)) {
            DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/get_jsapi_ticket");
            OapiGetJsapiTicketRequest req = new OapiGetJsapiTicketRequest();
            req.setHttpMethod("GET");
            OapiGetJsapiTicketResponse rsp = client.execute(req, accessToken);
            if (rsp.isSuccess()) {
                jsapiTicket = rsp.getBody();
            } else {
                log.error("获取钉钉签名失败:{},{},{}", rsp.getCode(), rsp.getMsg(), rsp.getErrmsg());
                throw new ApiException(rsp.getErrmsg());
            }
        }
        if (StringUtils.isNotBlank(jsapiTicket)) {
            redisCache.setCacheObject(cacheKey, jsapiTicket, 2, TimeUnit.HOURS);
        }
        return jsapiTicket;
    }

    @Autowired
    public void setRedisCache(RedisCache redisCache) {
        this.redisCache = redisCache;
    }


}
